package com.google.gwt.gfx.client;

import com.google.gwt.dom.client.Style.Cursor;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.gfx.client.DragEvent.Handler;
import com.google.gwt.gfx.client.GFXPanel.Tool;

/**
 * A type of {@link Tool} for panning a {@link GFXPanel} by dragging.
 */
public class DragPanTool<B extends GFXPanel<?, ?, ?>> implements Tool<B>,
		HasDragHandlers, DragEvent.Handler {

	private B buddyRef;

	private HandlerRegistration drag;

	private DragTool<B> dragToolRef = new DragTool<B>();

	private PanCommand<B> panCommandRef = new PanCommand<B>();

	@Override
	public HandlerRegistration addDragHandler(final Handler handler) {
		return dragToolRef.addDragHandler(handler);
	}

	/**
	 * @param buddy
	 *            {@link view()}
	 */
	public void bind(final B buddy) {
		buddyRef = buddy;

		panCommandRef.bind(buddy);
		dragToolRef.bind(buddy);
	}

	public B buddy() {
		return buddyRef;
	}

	@Override
	public void disable() {
		drag.removeHandler();
		dragToolRef.disable();
	}

	public DragTool<B> dragTool() {
		return dragToolRef;
	}

	@Override
	public void enable() {
		drag = dragToolRef.addDragHandler(this);
		dragToolRef.enable();
	}

	@Override
	public void fireEvent(GwtEvent<?> event) {
		dragToolRef.fireEvent(event);
	}

	/**
	 * @return {@link PanZoomTool#getAutoRefreshThreshold()}
	 */
	public int getAutoRefreshThreshold() {
		return panCommandRef.getAutoRefreshThreshold();
	}

	/**
	 * @return {@link PanZoomTool#isAutoRefresh()}
	 */
	public boolean isAutoRefresh() {
		return panCommandRef.isAutoRefresh();
	}

	@Override
	public void onDrag(DragEvent<?> event) {
		switch (event.getType()) {
		case Begin:
			panCommandRef.beginPanTo(event.getLeft(), event.getTop());
			buddy().getElement().getStyle().setCursor(Cursor.MOVE);
			buddy().setFocus(true);
			break;
		case Continue:
			panCommandRef.continuePanTo(event.getLeft(), event.getTop());
			break;
		case End:
			panCommandRef.endPan();
			buddy().getElement().getStyle().setCursor(Cursor.AUTO);
			break;
		default:
			break;
		}
	}

	public PanCommand<B> panCommand() {
		return panCommandRef;
	}

	/**
	 * @param autoRefreshCamera
	 *            {@link #isAutoRefresh()}
	 */
	public void setAutoRefresh(boolean autoRefreshCamera) {
		panCommandRef.setAutoRefresh(autoRefreshCamera);
	}

	/**
	 * @param autoRefreshThreshold
	 *            {@link #getAutoRefreshThreshold()}
	 */
	public void setAutoRefreshThreshold(int autoRefreshThreshold) {
		panCommandRef.setAutoRefreshThreshold(autoRefreshThreshold);
	}
}
